/*
 * serial.c
 *
 *  Created on: Dec 25, 2013
 *      Author: Ahmed
 */

/*
 * This file contains all the functions needed to communicate with the RS232 interface.
 *
 * Read from EEPROM, and send over the serial interface
 *
 */

#include "stm32f10x.h"
#include "main.h"
#include "datetime.h"
#include "storage.h"
#include "serial.h"

uint8_t TxCounter=0;
uint8_t TxBuffLen=0;
char	serial_data[30];
LogHeaderDef logHeader;
dataRecDef	dataRecord;
uint16_t	eepromReadAddr;
uint8_t		sizeof_sample;
SERIALSTATES serial_TX_state = SERIAL_INIT;

uint8_t USARTBuffer[USARTBufferSize];
extern userSettingsDef userSettings;		// store all user settings
extern uint16_t ISR_type;

/*
 * This function will read the EEPROM data after the user settings sections till
 * userSettings.eepromWriteAddr
 * It will parse the log headers, and read the following data records.
 * It will format the samples read in the format of dd/mm/yy,hh:mm,Temp,Humidity
 *
 * It returns a 0xFF in case it encounter an unexpected information
 * A FSM to handle transmitting the EEPROM content.
 * In the INIT State, it will send the Heading. If successful, it will change state to SEND_LOG_HEADER
 * And so on.
 * It will be called in the main loop whenever the TX buffer of the USART is empty
 * If succeeds in sending header, then change panel text to "Sending.." else display "
 */

void serial_dump_eeprom(void){

	switch (serial_TX_state) {
		case SERIAL_INIT:
			eepromReadAddr = sizeof_userSettingsStruct();
			sizeof_sample = sizeof_dataRecStruct();
			serial_send_string("Date,Time,Temperature,Humidity\n\r",32);
			serial_TX_state = TX_LOG_HEADER;
			break;
		case TX_LOG_HEADER:
			if(eepromReadAddr < userSettings.eepromWriteAddr){
				readLogHeader(eepromReadAddr, &logHeader);
				if (logHeader.separator != LOG_HEADER_ID) {	//something wrong, stop and return
					serial_TX_state = TX_LOG_HEADER;
					ISR_type |= ISR_USART_TX;	// Transfer Completed
					break;
				}
				eepromReadAddr+=sizeof_logHeaderStruct();
				serial_TX_state = TX_DATA;
			} else {
				serial_TX_state = TX_END;	// We reached end of stored data
			}
			ISR_type |= ISR_USART_TX;	// Transfer Completed
			break;
		case TX_DATA:
			readLogData(eepromReadAddr,&dataRecord);
			if(dataRecord.temperature == LOG_HEADER_ID){
				serial_TX_state = TX_LOG_HEADER;
				ISR_type |= ISR_USART_TX;	// call this function again from the main loop
			} else
			if(eepromReadAddr >= userSettings.eepromWriteAddr){
				serial_TX_state = TX_END;
				ISR_type |= ISR_USART_TX;	// call this function again from the main loop
			} else {
				epoch_to_string(logHeader.startLogTime,serial_data);
				serial_data[16]=',';
				dec_to_string(serial_data+17,dataRecord.temperature);
				serial_data[19]=',';
				dec_to_string(serial_data+20,dataRecord.humidity);
				serial_data[22]=0x0D;
				serial_data[23]=0x0A;
				serial_send_string(serial_data,24);
				logHeader.startLogTime+=logHeader.RTC_Alarm_Count;
				eepromReadAddr+=sizeof_sample;
			}
			break;
		case TX_END:
			break;

		default:
			break;
	}
}

/*
 * This function takes a buffer and send it to the USART1. It returns error 0xff is the text to be sent is longer than the USART
 * buffer or if previous transmission was not completed
 */

uint8_t serial_send_string(char *buff, uint8_t buffLen){
	uint8_t i;

    if (buffLen > USARTBufferSize) {	// check string length not bigger than memory allocated
		return 0xFF;
	}

    for (i = 0; i < buffLen; i++) {
    	USARTBuffer[i] = buff[i];
	}

    TxCounter=0;
    TxBuffLen = buffLen;

    // Enable the USART1 Transmit interrupt. Upon end of transmitting
    // all buffer, interrupt will disable the interrupt

	USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	return 0;
}
